package com.heima.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.admin.feign.ArticleFeign;
import com.heima.admin.feign.WemediaFeign;
import com.heima.admin.service.AdChannelService;
import com.heima.admin.service.AdSensitiveService;
import com.heima.admin.service.WemediaNewsAutoScanService;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.aliyun.util.UploadCredentials;
import com.heima.common.exception.CostomException;
import com.heima.common.fastdfs.FastDFSClient;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.admin.pojos.AdSensitive;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.article.pojos.ApAuthor;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import io.seata.spring.annotation.GlobalTransactional;
import net.sf.jsqlparser.expression.LongValue;
import org.apache.commons.net.nntp.NewsgroupInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {

    @Autowired
    private WemediaFeign wemediaFeign;

    @Autowired
    private FastDFSClient fastDFSClient;

    @Autowired
    private GreenImageScan greenImageScan;

    @Autowired
    private GreenTextScan greenTextScan;

    @Autowired
    private AdChannelService adChannelService;

    @Autowired
    private AdSensitiveService adSensitiveService;

    @Value("${fdfs.url}")
    private String fastUrl;


    @GlobalTransactional
    @Override
    public void autoScanByMediaNewsId(Integer id) throws Exception {
        //判断参数
        if (id == null) {
            throw new CostomException(ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "自媒体文章id不存在"));
        }
        //根据id查询出对应自媒体文章
        WmNews wmNews = wemediaFeign.findById(id);
        if (wmNews == null) {
            throw new CostomException(ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "文章不存在"));
        }

        //如果文章人工审核通过 并且发布时间小于当前时间的话 直接保存到app端的文章三表中
        if (wmNews.getStatus().equals((short) 4) && wmNews.getPublishTime().getTime() <= System.currentTimeMillis()) {
            saveAppArticle(wmNews);
            return;
        }

        //如果文章自动审核通过 并且发布时间小于当前时间的话 也直接保存到app端的文章三联表中；
        if (wmNews.getStatus().equals((short) 8) && wmNews.getPublishTime().getTime() <= System.currentTimeMillis()) {
            saveAppArticle(wmNews);
            return;
        }

        if (wmNews.getStatus().equals((short) 1)) {
            Map<String, Object> newsData = getNewsContentTextAndImages(wmNews);

            //审核文章内容
            boolean a = handleTextScan((String) newsData.get("text"), wmNews);
            if (!a) return;

            //审核图片内容
            boolean b = handleImageScan((List<String>) newsData.get("images"), wmNews);
            if (!b) return;

            //审核文章内容中有没有自管理的敏感词汇
            boolean c = MyhandleTextScan((String) newsData.get("text"), wmNews);
            if (!c) return;

            //如果以上的审核都没问题  判断是否到了发布时间 如果没到 设置为8 （审核通过待发布）
            if (wmNews.getPublishTime().getTime()>System.currentTimeMillis()){
                updateNewStatus(wmNews,(short)8,"审核通过，待发布");
                return;
            }

                //保存app端文章三联表 并设置Wmnews状态为 9 已发布 并补上app端文章id
            saveAppArticle(wmNews);
        }


    }

    /**
     * 保存app端文章三联表 并设置Wmnews状态为 9 已发布 并补上app端文章id
     * @param wmNews
     */
    private void saveAppArticle(WmNews wmNews) {
        ResponseResult responseResult = saveArticle(wmNews);
        if (!responseResult.getCode().equals(0)){
            throw new RuntimeException("文章审核保存app文章失败");
        }
        Long articleId = (Long)responseResult.getData();
        wmNews.setArticleId(articleId);
        updateNewStatus(wmNews,(short)9,"审核通过！");
    }

    @Autowired
    ArticleFeign articleFeign;


    /**
     * 真正的保存到app端
     * @param wmNews
     * @return
     */
    private ResponseResult saveArticle(WmNews wmNews) {
        ArticleDto dto = new ArticleDto();
        if (wmNews.getArticleId()!=null){
            dto.setId(wmNews.getArticleId());
        }
        dto.setContent(wmNews.getContent());
        //app的作者对象
        WmUser wmUser = wemediaFeign.findWmUserById(wmNews.getUserId().longValue());
        dto.setAuthorName(wmUser.getName());

        AdChannel channel = adChannelService.getOne(Wrappers.<AdChannel>lambdaQuery().eq(AdChannel::getId, wmNews.getChannelId()));
        dto.setChannelId(channel.getId());
        dto.setChannelName(channel.getName());
        dto.setImages(wmNews.getImages());
        dto.setTitle(wmNews.getTitle());
        dto.setLayout(wmNews.getType());
        dto.setLabels(wmNews.getLabels());
        dto.setPublishTime(wmNews.getPublishTime());
        dto.setCreatedTime(wmNews.getCreatedTime());
        return articleFeign.saveArticle(dto);
    }

    /**
     * 审核文本内容中有没有自管理的敏感词汇库
     *
     * @param text
     * @param wmNews
     * @return
     */
    private boolean MyhandleTextScan(String text, WmNews wmNews) {

        boolean a = true;
        ArrayList<String> list = new ArrayList<>();
        List<AdSensitive> sensitiveList = adSensitiveService.list();
        for (AdSensitive adSensitive : sensitiveList) {
            String sensitives = adSensitive.getSensitives();
            list.add(sensitives);
        }
        SensitiveWordUtil.initMap(list);
        Map<String, Integer> map = SensitiveWordUtil.matchWords(text);
        if (map.size() > 0) {
            updateNewStatus(wmNews, (short) 2, "文章内容中包含敏感词"+map);
            a = false;
        }
        return a;
    }

    /**
     * 审核图片
     *
     * @param images
     * @param wmNews
     * @return
     */
    private boolean handleImageScan(List<String> images, WmNews wmNews) throws Exception {
        if (images == null || images.size() == 0) {
            return true;
        }
        boolean flag = true;
        try {

            for (String image : images) {
                int i = image.indexOf("/");
                //得到第一个/的索引
                String groupName = image.substring(0, i);
                //从0索引开始 到/的索引结束 包头不包尾 切割
                String path = image.substring(i + 1);
                //从/的索引+1 到最后（如果不指定结束索引默认截完）切割
                byte[] imageByte = fastDFSClient.download(groupName, path);

                ArrayList<byte[]> bytes = new ArrayList<>();
                bytes.add(imageByte);
                Map imageMap = greenImageScan.imageScan(bytes);

                //审核不通过
                if (imageMap.get("suggestion").equals("block")) {
                    updateNewStatus(wmNews, (short) 2, "文章图片有违规");
                    flag = false;
                }
                //人工审核
                if (imageMap.get("suggestion").equals("review")) {
                    updateNewStatus(wmNews, (short) 3, "文章图片有不确定元素");
                    flag = false;
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
            flag = false;
        }

        return flag;

    }


    /**
     * 审核文本内容 并修改文章表
     *
     * @param text
     * @param wmNews
     * @return
     */
    private boolean handleTextScan(String text, WmNews wmNews) {

        boolean flag = true;

        try {
            Map map = greenTextScan.greeTextScan(text);
            //如果有敏感词 修改文章状态
            if (map.get("suggestion").equals("block")) {
                updateNewStatus(wmNews, (short) 2, "文本中有敏感词汇");
                flag = false;
            }
            if (map.get("suggestion").equals("review")) {
                //代表不确定 需要人工审核
                updateNewStatus(wmNews, (short) 3, "文本中有不确定词汇，转入人工审核");
                flag = false;
            }

        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        }
        return flag;
    }

    /**
     * 修改文章状态
     *
     * @param wmNews
     * @param i
     * @param msg
     */
    private void updateNewStatus(WmNews wmNews, short i, String msg) {
        wmNews.setStatus(i);
        wmNews.setReason(msg);
        ResponseResult responseResult = wemediaFeign.updateWmNews(wmNews);
        if (!responseResult.getCode().equals(0)) {
            throw new RuntimeException("修改自媒体文章失败");
        }
    }

    /**
     * 解析文章中的文本内容 和 所有图片
     *
     * @param wmNews
     * @return
     */
    private Map<String, Object> getNewsContentTextAndImages(WmNews wmNews) {
        StringBuilder sb = new StringBuilder();
        ArrayList<String> images = new ArrayList<>();
        List<Map> maps = JSON.parseArray(wmNews.getContent(), Map.class);
        for (Map map : maps) {
            if (map.get("type").equals("text")) {
                String value = (String) (map.get("value"));
                sb.append(value);
            }
            if (map.get("type").equals("image")) {
                String value = (String) map.get("value");
                String replace = value.replace(fastUrl, "");
                images.add(replace);
            }
        }
        if (wmNews.getImages().length() > 0 && wmNews.getImages() != null) {
            String images1 = wmNews.getImages();
            String[] imageList = images1.split(",");
            for (String s : imageList) {
                String replace = s.replace(fastUrl, "");
                images.add(replace);
            }
        }
        Map<String, Object> map = new HashMap<>();
        map.put("text", sb.toString());
        map.put("images", images);
        return map;
    }


}
